///*
// * ====================================================================
// * Licensed to the Apache Software Foundation (ASF) under one
// * or more contributor license agreements.  See the NOTICE file
// * distributed with this work for additional information
// * regarding copyright ownership.  The ASF licenses this file
// * to you under the Apache License, Version 2.0 (the
// * "License"); you may not use this file except in compliance
// * with the License.  You may obtain a copy of the License at
// *
// *   http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing,
// * software distributed under the License is distributed on an
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// * KIND, either express or implied.  See the License for the
// * specific language governing permissions and limitations
// * under the License.
// * ====================================================================
// *
// * This software consists of voluntary contributions made by many
// * individuals on behalf of the Apache Software Foundation.  For more
// * information on the Apache Software Foundation, please see
// * <http://www.apache.org/>.
// *
// */
//
//package com.quadcopter.background.webserver;
//
//import java.io.File;
//import java.io.IOException;
//import java.io.InterruptedIOException;
//import java.io.OutputStream;
//import java.io.OutputStreamWriter;
//import java.net.ServerSocket;
//import java.net.Socket;
//import java.net.URLDecoder;
//import java.util.Locale;
//
//import org.apache.http.ConnectionClosedException;
//import org.apache.http.HttpEntity;
//import org.apache.http.HttpEntityEnclosingRequest;
//import org.apache.http.HttpException;
//import org.apache.http.HttpRequest;
//import org.apache.http.HttpResponse;
//import org.apache.http.HttpServerConnection;
//import org.apache.http.HttpStatus;
//import org.apache.http.MethodNotSupportedException;
//import org.apache.http.entity.ContentProducer;
//import org.apache.http.entity.EntityTemplate;
//import org.apache.http.entity.FileEntity;
//import org.apache.http.impl.DefaultConnectionReuseStrategy;
//import org.apache.http.impl.DefaultHttpResponseFactory;
//import org.apache.http.impl.DefaultHttpServerConnection;
//import org.apache.http.params.BasicHttpParams;
//import org.apache.http.params.CoreConnectionPNames;
//import org.apache.http.params.CoreProtocolPNames;
//import org.apache.http.params.HttpParams;
//import org.apache.http.protocol.BasicHttpContext;
//import org.apache.http.protocol.BasicHttpProcessor;
//import org.apache.http.protocol.HttpContext;
//import org.apache.http.protocol.HttpRequestHandler;
//import org.apache.http.protocol.HttpRequestHandlerRegistry;
//import org.apache.http.protocol.HttpService;
//import org.apache.http.protocol.ResponseConnControl;
//import org.apache.http.protocol.ResponseContent;
//import org.apache.http.protocol.ResponseDate;
//import org.apache.http.protocol.ResponseServer;
//import org.apache.http.util.EntityUtils;
//
///**
// * Basic, yet fully functional and spec compliant, HTTP/1.1 file server.
// * <p>
// * Please note the purpose of this application is demonstrate the usage of HttpCore APIs.
// * It is NOT intended to demonstrate the most efficient way of building an HTTP file server. 
// * 
// *
// */
//public class ElementalHttpServer {
//
//    public static void main(String[] args) throws Exception {
//        if (args.length < 1) {
//            System.err.println("Please specify document root directory");
//            System.exit(1);
//        }
//        Thread t = new RequestListenerThread(8080, args[0]);
//        t.setDaemon(false);
//        t.start();
//    }
//    
//    static class HttpFileHandler implements HttpRequestHandler  {
//        
//        private final String docRoot;
//        
//        public HttpFileHandler(final String docRoot) {
//            super();
//            this.docRoot = docRoot;
//        }
//        
//        public void handle(
//                final HttpRequest request, 
//                final HttpResponse response,
//                final HttpContext context) throws HttpException, IOException {
//
//            String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
//            if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
//                throw new MethodNotSupportedException(method + " method not supported"); 
//            }
//            String target = request.getRequestLine().getUri();
//
//            if (request instanceof HttpEntityEnclosingRequest) {
//                HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
//                byte[] entityContent = EntityUtils.toByteArray(entity);
//                System.out.println("Incoming entity content (bytes): " + entityContent.length);
//            }
//            
//            final File file = new File(this.docRoot, URLDecoder.decode(target));
//            if (!file.exists()) {
//
//                response.setStatusCode(HttpStatus.SC_NOT_FOUND);
//                EntityTemplate body = new EntityTemplate(new ContentProducer() {
//                    
//                    public void writeTo(final OutputStream outstream) throws IOException {
//                        OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); 
//                        writer.write("<html><body><h1>");
//                        writer.write("File ");
//                        writer.write(file.getPath());
//                        writer.write(" not found");
//                        writer.write("</h1></body></html>");
//                        writer.flush();
//                    }
//                    
//                });
//                body.setContentType("text/html; charset=UTF-8");
//                response.setEntity(body);
//                System.out.println("File " + file.getPath() + " not found");
//                
//            } else if (!file.canRead() || file.isDirectory()) {
//                
//                response.setStatusCode(HttpStatus.SC_FORBIDDEN);
//                EntityTemplate body = new EntityTemplate(new ContentProducer() {
//                    
//                    public void writeTo(final OutputStream outstream) throws IOException {
//                        OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); 
//                        writer.write("<html><body><h1>");
//                        writer.write("Access denied");
//                        writer.write("</h1></body></html>");
//                        writer.flush();
//                    }
//                    
//                });
//                body.setContentType("text/html; charset=UTF-8");
//                response.setEntity(body);
//                System.out.println("Cannot read file " + file.getPath());
//                
//            } else {
//                
//                response.setStatusCode(HttpStatus.SC_OK);
//                FileEntity body = new FileEntity(file, "text/html");
//                response.setEntity(body);
//                System.out.println("Serving file " + file.getPath());
//                
//            }
//        }
//        
//    }
//    
//    static class RequestListenerThread extends Thread {
//
//        private final ServerSocket serversocket;
//        private final HttpParams params; 
//        private final HttpService httpService;
//        
//        public RequestListenerThread(int port, final String docroot) throws IOException {
//            this.serversocket = new ServerSocket(port);
//            this.params = new BasicHttpParams();
//            this.params
//                .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
//                .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
//                .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
//                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
//                .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1");
//
//            // Set up the HTTP protocol processor
//            BasicHttpProcessor httpproc = new BasicHttpProcessor();
//            httpproc.addInterceptor(new ResponseDate());
//            httpproc.addInterceptor(new ResponseServer());
//            httpproc.addInterceptor(new ResponseContent());
//            httpproc.addInterceptor(new ResponseConnControl());
//            
//            // Set up request handlers
//            HttpRequestHandlerRegistry registry = new HttpRequestHandlerRegistry();
//            registry.register("*", new HttpFileHandler(docroot));
//            
//
//            httpService = new HttpService(httpproc, new DefaultConnectionReuseStrategy(),new DefaultHttpResponseFactory());
//            httpService.setHandlerResolver(registry);
//            httpService.setParams(params);
//        }
//        
//        public void run() {
//            System.out.println("Listening on port " + this.serversocket.getLocalPort());
//            while (!Thread.interrupted()) {
//                try {
//                    // Set up HTTP connection
//                    Socket socket = this.serversocket.accept();
//                    DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
//                    System.out.println("Incoming connection from " + socket.getInetAddress());
//                    conn.bind(socket, this.params);
//
//                    // Start worker thread
//                    Thread t = new WorkerThread(this.httpService, conn);
//                    t.setDaemon(true);
//                    t.start();
//                } catch (InterruptedIOException ex) {
//                    break;
//                } catch (IOException e) {
//                    System.err.println("I/O error initialising connection thread: " 
//                            + e.getMessage());
//                    break;
//                }
//            }
//        }
//    }
//    
//    static class WorkerThread extends Thread {
//
//        private final HttpService httpservice;
//        private final HttpServerConnection conn;
//        
//        public WorkerThread(
//                final HttpService httpservice, 
//                final HttpServerConnection conn) {
//            super();
//            this.httpservice = httpservice;
//            this.conn = conn;
//        }
//        
//        public void run() {
//            System.out.println("New connection thread");
//            HttpContext context = new BasicHttpContext(null);
//            try {
//                while (!Thread.interrupted() && this.conn.isOpen()) {
//                    this.httpservice.handleRequest(this.conn, context);
//                }
//            } catch (ConnectionClosedException ex) {
//                System.err.println("Client closed connection");
//            } catch (IOException ex) {
//                System.err.println("I/O error: " + ex.getMessage());
//            } catch (HttpException ex) {
//                System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage());
//            } finally {
//                try {
//                    this.conn.shutdown();
//                } catch (IOException ignore) {}
//            }
//        }
//
//    }
//    
//}
